package e.odbo.data.model;

import com.openbravo.data.loader.serialize.Datas;
import e.odbo.data.format.Formats;
import e.odbo.data.generator.I_Generator;

import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Clob;
import java.util.Date;

public abstract class ColumnType<T> {
    public final static String DIALECT_Default="sample";
    protected String type;
    protected int length;
    protected int size2;
    protected String dialectName=DIALECT_Default;

    protected Datas dataType;
    protected Formats format;

    protected T defaultValue=null;

    protected I_Generator<T> defaultGenerator=null;

    protected boolean lengthSupport=false;

    public static ColumnType INT=new ColumnType<Integer>("INT",Datas.INT,Formats.INT){};

    public ColumnType() {
    }

    //
    //默认值用级链方式：INT.defaultV(20);
    //
    //public static ColumnType INT(int defaultValue){
    //    return new ColumnType<Integer>("int",Datas.INT,defaultValue){};
    //}
    /**
    SQL类型	        JDBC/Java类型	        setXXX	                updateXXX
     ------------&---------------------&-------------------&--------------------->>>>>>
    VARCHAR	        java.lang.String	    setString	            updateString
    CHAR	        java.lang.String	    setString	            updateString
    LONGVARCHAR	    java.lang.String	    setString	            updateString
    BIT	            boolean	                setBoolean	            updateBoolean
    NUMERIC	        java.math.BigDecimal	setBigDecimal	        updateBigDecimal
    TINYINT	        byte	                setByte	                updateByte
    SMALLINT	    short	                setShort	            updateShort
    INTEGER	        int	                    setInt	                updateInt
    BIGINT	        long	                setLong             	updateLong
    REAL	        float	                setFloat	            updateFloat
    FLOAT	        float	                setFloat	            updateFloat
    DOUBLE	        double	                setDouble	            updateDouble
    VARBINARY	    byte[ ]	                setBytes	            updateBytes
    BINARY	        byte[ ]	                setBytes	            updateBytes
    DATE	        java.sql.Date	        setDate	                updateDate
    TIME	        java.sql.Time	        setTime	                updateTime
    TIMESTAMP	    java.sql.Timestamp	    setTimestamp	        updateTimestamp
    CLOB	        java.sql.Clob	        setClob	                updateClob
    BLOB	        java.sql.Blob	        setBlob	                updateBlob
    ARRAY	        java.sql.Array	        setARRAY	            updateARRAY
    REF	            java.sql.Ref	        SetRef	                updateRef
    STRUCT	        java.sql.Struct	        SetStruct	            updateStruct
    **/

    public static ColumnType VARCHAR=VARCHAR(255);

    public static ColumnType VARCHAR(int length){
        return new ColumnType<String>("VARCHAR",length,Datas.STRING,Formats.STRING){};
    }

    public static ColumnType BOOLEAN=new ColumnType<Boolean>("BOOLEAN",Datas.BOOLEAN,Formats.BOOLEAN){};

    public static ColumnType DOUBLE=new ColumnType<Double>("DOUBLE",Datas.DOUBLE,Formats.DOUBLE){};

    public static ColumnType LONG=new ColumnType<Long>("LONG",Datas.LONG,Formats.DOUBLE){};

    public static ColumnType TIMESTAMP=new ColumnType<Date>("TIMESTAMP",Datas.TIMESTAMP,Formats.TIMESTAMP){};


    //public static ColumnType TIME=new ColumnType<Date>("TIME",Datas.TIMESTAMP,Formats.TIMESTAMP){};

    public static ColumnType BIT=new ColumnType<Boolean>("BIT",Datas.BOOLEAN,Formats.BOOLEAN){};

    public static ColumnType SMALLINT=new ColumnType<Float>("SMALLINT",Datas.SHORT,Formats.INT){};

    public static ColumnType CLOB=new ColumnType<Clob>("CLOB",Datas.CLOB,Formats.NULL){};

    public static ColumnType BLOB=new ColumnType<Blob>("BLOB",Datas.BLOB,Formats.NULL){};

    public static ColumnType BIGDECIMAL=new ColumnType<BigDecimal>("NUMERIC",Datas.BIGDECIMAL,Formats.BIGDECIMAL){};

    public ColumnType(String type, Datas dataType,Formats format) {
        this.type = type;
        this.dataType = dataType;
        length =size2=-1;
        this.format=format;
    }


    public ColumnType(String type, int length, Datas dataType,Formats format) {
        this.type = type;
        this.length = length;
        this.dataType = dataType;
        this.size2=-1;
        this.format=format;
        lengthSupport=length!=-1;
    }

    public ColumnType(String type, int size1, int size2, Datas dataType,Formats format) {
        this.type = type;
        this.length = size1;
        this.size2 = size2;
        this.dataType = dataType;
        this.format=format;
        lengthSupport=length!=-1;
    }

    public ColumnType(String type, Datas dataType,Formats format, T defaultValue) {
        this.type = type;
        this.dataType = dataType;
        length =size2=-1;
        this.defaultValue=defaultValue;
        this.format=format;

    }

    public ColumnType(String type, int length, Datas dataType, Formats format,T defaultValue) {
        this.type = type;
        this.length = length;
        this.dataType = dataType;
        this.size2=-1;
        this.defaultValue=defaultValue;
        this.format=format;
        lengthSupport=length!=-1;
    }

    public ColumnType(String type, int length, int size2, Datas dataType, Formats format,T defaultValue) {
        this.type = type;
        this.length = length;
        this.dataType = dataType;
        this.size2=size2;
        this.defaultValue=defaultValue;
        this.format=format;
        lengthSupport=length!=-1;
    }


    public String getType() {
        return type;
    }

    public String buildTypeString(){
        if(lengthSupport) {
            if (length != -1 && size2 != -1)
                return type + "(" + length + "," + size2 + ")";
            else if (length != -1)
                return type + "(" + length + ")";
        }
       return type;
    }

    public int getLength() {
        return length;
    }

    public int getSize2() {
        return size2;
    }

    public Datas getDataType() {
        return dataType;
    }


    public T getDefaultValue() {
        return defaultValue;
    }

    /**
     *
     * 长度因设置时定，不用级名链方试好看，用方法方式。如：VARCHAR(60)
     *
    public ColumnType length(int length){
        this.length=length;
        return this;
    }

    public ColumnType length(int length,int size2){
        this.length=length;
        this.size2=size2;
        return this;
    }**/

    public ColumnType defaultV(T value){
        ColumnType<T> cloned=new ColumnType<T>(this.type,this.length,this.size2,this.dataType,this.format,value){};
        cloned.dialectName=dialectName;
        return cloned;
    }

    public ColumnType defaultGenerator(I_Generator<T> generator){
        ColumnType cloned=new ColumnType<T>(this.type,this.length,this.size2,this.dataType,this.format){};
        cloned.dialectName=dialectName;
        cloned.defaultGenerator=generator;
        return cloned;
    }

    public String getDialectName() {
        return dialectName;
    }

    public Formats getFormat() {
        return format;
    }

    public I_Generator<T> getDefaultGenerator() {
        return defaultGenerator;
    }

    public ColumnType<T> clone(){
        ColumnType<T> cloned=new ColumnType<T>(this.type,this.length,this.size2,this.dataType,this.format){};
        cloned.dialectName=dialectName;
        cloned.defaultValue=defaultValue;
        cloned.defaultGenerator=defaultGenerator;
        return cloned;
    }

    public ColumnType<T> union(ColumnType<T> distType){
        ColumnType<T> cloned=new ColumnType<T>(distType.type,this.length,this.size2,distType.dataType,distType.format){};
        cloned.lengthSupport=distType.lengthSupport;
        cloned.dialectName=dialectName;
        cloned.defaultValue=defaultValue;
        cloned.defaultGenerator=defaultGenerator;
        return cloned;
    }
}
